package io.gitee.zhangbinhub.admin.oauth.service

import com.mybatisflex.core.query.QueryChain
import com.mybatisflex.core.query.QueryWrapper
import com.mybatisflex.core.update.UpdateChain
import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.cloud.resource.server.tools.TokenTools
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.common.vo.CustomerQueryPageVo
import io.gitee.zhangbinhub.admin.oauth.base.OauthBaseService
import io.gitee.zhangbinhub.admin.oauth.entity.Application
import io.gitee.zhangbinhub.admin.oauth.po.ApplicationPo
import io.gitee.zhangbinhub.admin.oauth.po.ApplicationQueryPo
import io.gitee.zhangbinhub.admin.oauth.repo.ApplicationRepository
import io.gitee.zhangbinhub.admin.oauth.repo.UserRepository
import org.noear.solon.annotation.Component
import org.noear.solon.annotation.Inject
import org.noear.solon.data.annotation.Transaction

@Component
open class ApplicationService(
    @Inject userRepository: UserRepository,
    private val applicationRepository: ApplicationRepository
) : OauthBaseService(userRepository) {

    fun getAppList(): MutableList<Application> = applicationRepository.selectAll()

    @Throws(WebException::class)
    fun getAccessibleAppList(loginNo: String?): MutableList<Application> =
        applicationRepository.selectListByQuery(
            QueryWrapper.create()
                .orderBy(Application::identify, true)
                .orderBy(Application::appName, true)
        ).let { applicationList ->
            if (!CommonTools.isNullStr(loginNo)) {
                val currUserInfo = getUserInfoByLoginNo(loginNo!!) ?: throw WebException("无法获取当前用户信息")
                val authAppIdSet = currUserInfo.roleSet.map { role -> role.appId }.toSet()
                applicationList.filter { application ->
                    authAppIdSet.contains(application.id)
                }
            } else {
                applicationList
            }
        }.toMutableList()

    @Throws(WebException::class)
    fun getOwnAppList(loginNo: String): MutableList<Application> {
        val currUserInfo = getUserInfoByLoginNo(loginNo) ?: throw WebException("无法获取当前用户信息")
        return if (isSuper(currUserInfo)) {
            applicationRepository.selectListByQuery(
                QueryWrapper.create()
                    .orderBy(Application::identify, true)
                    .orderBy(Application::appName, true)
            )
        } else {
            applicationRepository.selectListByIds(listOf(TokenTools.getAccessTokenModel()?.clientId ?: ""))
        }
    }

    @Transaction
    open fun doCreate(applicationPo: ApplicationPo): Application =
        Application(
            appName = applicationPo.appName!!,
            secret = CommonTools.getUuid32(),
            scope = applicationPo.scope?.trim()?.replace("，", ",") ?: "",
            identify = applicationPo.identify?.trim() ?: "",
            accessTokenValiditySeconds = applicationPo.accessTokenValiditySeconds,
            refreshTokenValiditySeconds = applicationPo.refreshTokenValiditySeconds,
            covert = true
        ).also {
            applicationRepository.insert(it)
        }

    @Transaction
    @Throws(WebException::class)
    open fun doUpdate(applicationPo: ApplicationPo): Application =
        applicationRepository.selectOneById(applicationPo.id!!)?.copy(
            appName = applicationPo.appName!!,
            scope = applicationPo.scope?.trim()?.replace("，", ",") ?: "",
            identify = applicationPo.identify?.trim() ?: "",
            accessTokenValiditySeconds = applicationPo.accessTokenValiditySeconds,
            refreshTokenValiditySeconds = applicationPo.refreshTokenValiditySeconds
        )?.also {
            applicationRepository.update(it, false)
        } ?: throw WebException("找不到信息")

    @Transaction
    @Throws(WebException::class)
    open fun doUpdateSecret(appId: String): Application =
        applicationRepository.selectOneById(appId)?.copy(
            secret = CommonTools.getUuid32()
        )?.also {
            UpdateChain.of(applicationRepository)
                .set(Application::secret, it.secret)
                .where(Application::id).eq(it.id)
                .update()
        } ?: throw WebException("找不到信息")

    @Transaction
    open fun doDelete(idList: MutableList<String>) {
        applicationRepository.selectListByIds(idList)
            .filter { it.covert }
            .map { it.id }
            .let { applicationRepository.deleteBatchByIds(it) }
    }

    fun doQuery(applicationQueryPo: ApplicationQueryPo): CustomerQueryPageVo<Application> =
        QueryChain.of(applicationRepository)
            .where(Application::appName)
            .like(applicationQueryPo.appName, !CommonTools.isNullStr(applicationQueryPo.appName))
            .let { queryChain ->
                doPageQuery(applicationQueryPo.queryParam!!, queryChain)
            }

    fun getApp(appId: String): Application? = applicationRepository.selectOneById(appId)

}
